#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <sys/signal.h>

#pragma pack(push)
#pragma pack(1)     //1字节对齐

typedef struct {
	char		RIFFNAME[4];
	unsigned int	nRIFFSize;
	char		WAVNAME[4];
	char		FMTNAME[4];
	unsigned int	nFMTSize;
	unsigned short	nAudioFormat;
	unsigned short  nChannels;
	unsigned int	nSampleRate; /*采样频率*/
	unsigned int	nBytesPerSecond; /*每秒所需字节数*/
	unsigned short	nBlockAlign; /*数据块对齐单位,每个采样需要的字节数*/
	unsigned short	wBitsPerSample; /*每个采样需要的bit数*/
	char		DATANAME[4];
	unsigned int	nDataSize;
} WAVFLIEHEAD;

#pragma pack(pop) /* 恢复先前的pack设置 */

WAVFLIEHEAD FileHeader;

void wav_head_print(void)
{
	printf("RIFFNAME:%c%c%c%c\n", FileHeader.RIFFNAME[0], FileHeader.RIFFNAME[1], FileHeader.RIFFNAME[2], FileHeader.RIFFNAME[3]);
	printf("RIFFSize:%d\n", FileHeader.nRIFFSize);
	printf("WAVNAME:%c%c%c%c\n", FileHeader.WAVNAME[0], FileHeader.WAVNAME[1], FileHeader.WAVNAME[2], FileHeader.WAVNAME[3]);
	printf("FMTNAME:%c%c%c%c\n", FileHeader.FMTNAME[0], FileHeader.FMTNAME[1], FileHeader.FMTNAME[2], FileHeader.FMTNAME[3]);
	printf("FMTSize:%d\n", FileHeader.nFMTSize);
	printf("AudioFormat:%d\n", FileHeader.nAudioFormat);
	printf("Channels:%d\n", FileHeader.nChannels);
	printf("SampleRate:%d\n", FileHeader.nSampleRate);
	printf("BytesPerSecond:%d\n", FileHeader.nBytesPerSecond);
	printf("BlockAlign:%d\n", FileHeader.nBlockAlign);
	printf("BitsPerSample:%d\n", FileHeader.wBitsPerSample);
	printf("DATANAME:%c%c%c%c\n", FileHeader.DATANAME[0], FileHeader.DATANAME[1], FileHeader.DATANAME[2], FileHeader.DATANAME[3]);
	printf("DataSize:%d\n", FileHeader.nDataSize);
}

int main(int argc, char const *argv[])
{
	unsigned int rate = 16000;
	unsigned short channels = 2, bits = 16;
	int option_index, c;
	static const char short_options[] = "hs:d:r:v:c:b:p:";
	static const struct option long_options[] = {
		{"help",no_argument,0,'h'},
		{"source pcm file name",required_argument,0,'s'},
		{"destination wav file name",required_argument,0,'d'},
		{"rate",required_argument,0,'r'},
		{"channels",required_argument,0,'r'},
		{0, 0, 0, 0}
	};
	char file_name_wav[100]={0,};
	char file_name_pcm[100]={0,};

	while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1)  {
		switch(c) {
			case 'h':
				printf("help\n");
				return 0;
			case 'd':
				strcpy(file_name_wav,optarg);
				break;
			case 's':
				strcpy(file_name_pcm,optarg);
				break;
			case 'r':
				rate = strtol(optarg, NULL, 0);
				break;
			case 'c':
				channels = strtol(optarg, NULL, 0);
				break;
			case 'b':
				bits = strtol(optarg, NULL, 0);
				break;
			default:
				printf("unsupport cmd,try -h for help\n");
				return 1;
		}
	}

	FileHeader.RIFFNAME[0] = 'R';
	FileHeader.RIFFNAME[1] = 'I';
	FileHeader.RIFFNAME[2] = 'F';
	FileHeader.RIFFNAME[3] = 'F';

	FileHeader.WAVNAME[0] = 'W';
	FileHeader.WAVNAME[1] = 'A';
	FileHeader.WAVNAME[2] = 'V';
	FileHeader.WAVNAME[3] = 'E';

	FileHeader.FMTNAME[0] = 'f';
	FileHeader.FMTNAME[1] = 'm';
	FileHeader.FMTNAME[2] = 't';
	FileHeader.FMTNAME[3] = 0x20;
	FileHeader.nFMTSize =16;//SND_PCM_FORMAT_S16_LE
	FileHeader.nAudioFormat = 1;

	FileHeader.DATANAME[0] = 'd';
	FileHeader.DATANAME[1] = 'a';
	FileHeader.DATANAME[2] = 't';
	FileHeader.DATANAME[3] = 'a';
	FileHeader.wBitsPerSample = bits;
	FileHeader.nBlockAlign =2;
	FileHeader.nSampleRate =rate;
	FileHeader.nBytesPerSecond = rate * FileHeader.nBlockAlign;
	FileHeader.nChannels = channels;
	wav_head_print();

	int nFileLen = 0;
	int nSize = sizeof(FileHeader);

	FILE *fp_s = NULL;
	FILE *fp_d = NULL;

	fp_s = fopen(file_name_pcm, "rb");
	if (fp_s == NULL)
		return -1;

	fp_d = fopen(file_name_wav, "wb+");
	if (fp_d == NULL)
		return -2;


	int nWrite =fwrite(&FileHeader, 1, nSize, fp_d);
	if (nWrite != nSize)
	{
		fclose(fp_s);
		fclose(fp_d);
		return -3;
	}

	while( !feof(fp_s))
	{
		char readBuf[4096];
		int nRead = fread(readBuf, 1,4096, fp_s);
		if (nRead >0)
		{
			fwrite(readBuf,1, nRead, fp_d);
		}

		nFileLen += nRead;
	}
	fseek(fp_d, 0L, SEEK_SET);

	FileHeader.nRIFFSize = nFileLen - 8 +nSize;
	FileHeader.nDataSize = nFileLen;
	nWrite =fwrite(&FileHeader, 1, nSize, fp_d);
	if (nWrite != nSize)
	{
		fclose(fp_s);
		fclose(fp_d);
		return -4;
	}

	fclose(fp_s);
	fclose(fp_d);

	return nFileLen;
}

